#ifndef _ATADRIVER_H_
#define _ATADRIVER_H_

typedef unsigned long Boolean;
typedef unsigned long DWORD;

#define SUCCESS(p) (p!=0)
#define FAILED(p) (p==0)

struct IDEDriveInformation
{
	unsigned short wGenConfig;
	unsigned short wNumCyls;
	unsigned short wReserved2;
	unsigned short wNumHeads;
	unsigned short wReserved5;
	unsigned short wNumSectorsPerTrack;
	unsigned short wVendorUnique[3];
	char sSerialNumber[20];
	unsigned short wBufferType;
	unsigned short wBufferSize;
	unsigned short wECCSize;
	char sFirmwareRev[8];
	char sModelNumber[40];
	unsigned short wMoreVendorUnique;
	unsigned short wReserved48;
	struct {
		unsigned short reserved1:8;
		unsigned short DMA:1;
		unsigned short LBA:1;
		unsigned short DisIORDY:1;
		unsigned short IORDY:1;
		unsigned short SoftRe:1;
		unsigned short Overlap:1;
		unsigned short Queue:1;
		unsigned short InlDMA:1;
	} wCapabilities;
	unsigned short wReserved1;
	unsigned short wPIOTiming;
	unsigned short wDMATiming;
	struct {
		unsigned short CHSNumber:1;
		unsigned short CycleNumber:1;
		unsigned short UnltraDMA:1;
		unsigned short reserved:13;
	} wFieldValidity;
	unsigned short wNumCurCyls;
	unsigned short wNumCurHeads;
	unsigned short wNumCurSectorsPerTrack;
	unsigned short wCurSectorsLow;
	unsigned short wCurSectorsHigh;
	struct {
		unsigned short CurNumber:8;
		unsigned short Multi:1;
		unsigned short reserved1:7;
	} wMultSectorStuff;
	unsigned long dwTotalSectors;
	unsigned short wSingleWordDMA;
	struct {
		unsigned short Mode0:1;
		unsigned short Mode1:1;
		unsigned short Mode2:1;
		unsigned short Reserved1:5;
		unsigned short Mode0Sel:1;
		unsigned short Mode1Sel:1;
		unsigned short Mode2Sel:1;
		unsigned short Reserved2:5;
	} wMultiWordDMA;
	struct {
		unsigned short AdvPOIModes:8;
		unsigned short reserved:8;
	} wPIOCapacity;
	unsigned short wMinMultiWordDMACycle;
	unsigned short wRecMultiWordDMACycle;
	unsigned short wMinPIONoFlowCycle;
	unsigned short wMinPOIFlowCycle;
	unsigned short wReserved69[11];
	struct {
		unsigned short Reserved1:1;
		unsigned short ATA1:1;
		unsigned short ATA2:1;
		unsigned short ATA3:1;
		unsigned short ATA4:1;
		unsigned short ATA5:1;
		unsigned short ATA6:1;
		unsigned short ATA7:1;
		unsigned short ATA8:1;
		unsigned short ATA9:1;
		unsigned short ATA10:1;
		unsigned short ATA11:1;
		unsigned short ATA12:1;
		unsigned short ATA13:1;
		unsigned short ATA14:1;
		unsigned short Reserved2:1;
	} wMajorVersion;
	unsigned short wMinorVersion;
	unsigned short wReserved82[6];
	struct {
		unsigned short Mode0:1;
		unsigned short Mode1:1;
		unsigned short Mode2:1;
		unsigned short Mode3:1;
		unsigned short Mode4:1;
		unsigned short Mode5:1;
		unsigned short Mode6:1;
		unsigned short Mode7:1;
		unsigned short Mode0Sel:1;
		unsigned short Mode1Sel:1;
		unsigned short Mode2Sel:1;
		unsigned short Mode3Sel:1;
		unsigned short Mode4Sel:1;
		unsigned short Mode5Sel:1;
		unsigned short Mode6Sel:1;
		unsigned short Mode7Sel:1;
	} wUltraDMA;
	unsigned short wReserved89[167];
};

extern "C" {
Boolean __IDEWaitForDrive               (DWORD Controller, DWORD Drive);
DWORD   __IDEReadFromPortsCHS           (DWORD Controller, DWORD Drive, DWORD Cylinder, DWORD Head, DWORD Sector, DWORD SectorCount, void* Buffer, DWORD MaxBufferLen);
DWORD   __IDEFillSectorsWithDWORD       (DWORD Controller, DWORD Drive, DWORD LBA28, DWORD NumberofSectors, DWORD FillWithDWORD);
DWORD   __IDESetTransferMode            (DWORD Controller, DWORD Drive, DWORD TransferMode);
DWORD   __IDEWriteBlockToPortsLBA28     (DWORD Controller, DWORD Drive, DWORD LBA28, DWORD SectorsPerBlock, DWORD BlockCount, void* SourceBuffer);
Boolean __IDECheckControllerExistence   (DWORD Controller);
DWORD   __IDEReadBlockFromPortsLBA28    (DWORD Controller, DWORD Drive, DWORD LBA28, DWORD SectorsPerBlock, DWORD BlockCount, void* Buffer, DWORD MaxBufferLen);
DWORD   __IDESetBlockSize               (DWORD Controller, DWORD Drive, DWORD SectorsPerBlock);
Boolean __IDECheckDriveExistence        (DWORD Controller, DWORD Drive);
DWORD   __IDESleep                      (DWORD Controller, DWORD Drive);
DWORD   __IDERecalibrate                (DWORD Controller, DWORD Drive);
DWORD   __IDEWriteToPortsLBA28          (DWORD Controller, DWORD Drive, DWORD LBA28, DWORD SectorCount, void* SourceBuffer);
DWORD __IDEReadFromPortsLBA28           (DWORD Controller, DWORD Drive, DWORD LBA28, DWORD SectorCount, void* Buffer, DWORD MaxBufferLen);
DWORD   __IDEDiagnose                   (DWORD Controller);
Boolean __IDEIdentifyDrive              (DWORD Controller, DWORD Drive, char* Buffer, DWORD BufferLength);
DWORD   __IDEProbe                      (void);
}

#define IDE_TYPICAL_TIMEOUT                        0x00001000

// General IDE ports
#define IDEC_PORT_ALTERNATESTATUS                  0X000003F8 // Read
#define IDEC_PORT_DEVICECONTROL                    0X000003F8 // Write
#define IDEC_PORT_DRIVEADDRESS                     0X000003F9 // Read
// 
#define IDE_PORT_OFFSET_DATA                       0x00000000
#define IDE_PORT_OFFSET_ERROR                      0x00000001
#define IDE_PORT_OFFSET_FEATURES                   0x00000001
#define IDE_PORT_OFFSET_SECTORCOUNT                0x00000002
#define IDE_PORT_OFFSET_SECTORNUMBER               0x00000003
#define IDE_PORT_OFFSET_LBABITS0TO7                0x00000003
#define IDE_PORT_OFFSET_CYLINDERLOW                0x00000004
#define IDE_PORT_OFFSET_LBABITS8TO15               0x00000004
#define IDE_PORT_OFFSET_CYLINDERHIGH               0x00000005
#define IDE_PORT_OFFSET_LBABITS16TO23              0x00000005
#define IDE_PORT_OFFSET_DRIVEHEAD                  0x00000006
#define IDE_PORT_OFFSET_LBABITS24TO27              0x00000006
#define IDE_PORT_OFFSET_STATUS                     0x00000007
#define IDE_PORT_OFFSET_COMMAND                    0x00000007
//
// PIDEC_PORT = Primary IDE Controller Port
#define PIDEC_PORT_BASE                            0x000001F0 // The base port for PIDEC (Primary IDE Controller)
#define PIDEC_PORT_DATA                            0x000001F0 // Read/Write
#define PIDEC_PORT_ERROR                           0x000001F1 // Read
#define PIDEC_PORT_FEATURES                        0x000001F1 // Write
#define PIDEC_PORT_SECTORCOUNT                     0x000001F2 // Read/Write
#define PIDEC_PORT_SECTORNUMBER                    0x000001F3 // Read/Write
#define PIDEC_PORT_LBABITS0TO7                     0x000001F3 // Read/Write
#define PIDEC_PORT_CYLINDERLOW                     0x000001F4 // Read/Write
#define PIDEC_PORT_LBABITS8TO15                    0x000001F4 // Read/Write
#define PIDEC_PORT_CYLINDERHIGH                    0x000001F5 // Read/Write
#define PIDEC_PORT_LBABITS16TO23                   0x000001F5 // Read/Write
#define PIDEC_PORT_DRIVEHEAD                       0x000001F6 // Read/Write
#define PIDEC_PORT_LBABITS24TO27                   0x000001F6 // Read/Write
#define PIDEC_PORT_STATUS                          0x000001F7 // Read
#define PIDEC_PORT_COMMAND                         0x000001F7 // Write

// SIDEC_PORT = Secondary IDE Controller Port
#define SIDEC_PORT_BASE                            0x00000170 // The base port for SIDEC (Secodnary IDE Controller)
#define SIDEC_PORT_DATA                            0x00000170 // Read/Write
#define SIDEC_PORT_ERROR                           0x00000171 // Read
#define SIDEC_PORT_FEATURES                        0x00000171 // Write
#define SIDEC_PORT_SECTORCOUNT                     0x00000172 // Read/Write
#define SIDEC_PORT_SECTORNUMBER                    0x00000173 // Read/Write
#define SIDEC_PORT_LBABITS0TO7                     0x00000173 // Read/Write
#define SIDEC_PORT_CYLINDERLOW                     0x00000174 // Read/Write
#define SIDEC_PORT_LBABITS8TO15                    0x00000174 // Read/Write
#define SIDEC_PORT_CYLINDERHIGH                    0x00000175 // Read/Write
#define SIDEC_PORT_LBABITS16TO23                   0x00000175 // Read/Write
#define SIDEC_PORT_DRIVEHEAD                       0x00000176 // Read/Write
#define SIDEC_PORT_LBABITS24TO27                   0x00000176 // Read/Write
#define SIDEC_PORT_STATUS                          0x00000177 // Read
#define SIDEC_PORT_COMMAND                         0x00000177 // Write
 
// Attached to the end of some of the commands are ...
//   ... W = With
//   ... WO = Without
// MIDE_CMD = Mandatory IDE Command
#define MIDE_CMD_EXECUTEDRIVEDIAGNOSTIC            0x00000090
#define MIDE_CMD_FORMATTRACK                       0x00000050
#define MIDE_CMD_INITIALIZEDRIVEPARAMS             0x00000091
#define MIDE_CMD_READLONGWR                        0x00000022
#define MIDE_CMD_READLONGWOR                       0x00000023
#define MIDE_CMD_READSECTORSWR                     0x00000020
#define MIDE_CMD_READSECTORSWOR                    0x00000021
#define MIDE_CMD_READVERIFYSECTORSWR               0x00000040
#define MIDE_CMD_READVERIFYSECTORSWOR              0x00000041
#define MIDE_CMD_RECALIBRATE                       0x00000010
#define MIDE_CMD_SEEK                              0x00000070
#define MIDE_CMD_WRITELONGWR                       0x00000032
#define MIDE_CMD_WRITELONGWOR                      0x00000033
#define MIDE_CMD_WRITESECTORSWR                    0x00000030
#define MIDE_CMD_WRITESECTORSWOR                   0x00000031
 
// OIDE_CMD = Optional IDE Command
#define OIDE_CMD_ACKNOWLEDGEMEDIACHANGE            0x000000DB
#define OIDE_CMD_BOOTPOSTBOOT                      0x000000DC
#define OIDE_CMD_BOOTPREBOOT                       0x000000DD
#define OIDE_CMD_CHECKPOWERMODE                    0x000000E5
#define OIDE_CMD_DOORLOCK                          0x000000DE
#define OIDE_CMD_DOORUNLOCK                        0x000000DF
#define OIDE_CMD_IDENTIFYDRIVE                     0x000000EC
#define OIDE_CMD_IDENTIFYDEVICE                    0x000000EC
#define OIDE_CMD_IDLE                              0x000000E3
#define OIDE_CMD_IDLEIMMEDIATE                     0x000000E1
#define OIDE_CMD_NOP                               0x00000000
#define OIDE_CMD_READBUFFER                        0x000000E4
#define OIDE_CMD_READDMAWR                         0x000000C8
#define OIDE_CMD_READDMAWOR                        0x000000C9
#define OIDE_CMD_READMULTIPLE                      0x000000C4
#define OIDE_CMD_SETFEATURES                       0x000000EF
#define OIDE_CMD_SETMULTIPLEMODE                   0x000000C6
#define OIDE_CMD_SLEEP                             0x000000E6
#define OIDE_CMD_STANDBY                           0x000000E2
#define OIDE_CMD_STANDBYIMMEDIATE                  0x000000E0
#define OIDE_CMD_WRITEBUFFER                       0x000000C8
#define OIDE_CMD_WRITEDMAWR                        0x000000CA
#define OIDE_CMD_WRITEDMAWOR                       0x000000CB
#define OIDE_CMD_WRITEMULTIPLE                     0x000000C5
#define OIDE_CMD_WRITESAME                         0x000000E9
#define OIDE_CMD_WRITEVERIFY                       0x0000003C
// 
// IDE, Drive/Head Register bitmask
#define IDE_DRIVEHEADREG_HS0                       0x00000001
#define IDE_DRIVEHEADREG_HS1                       0x00000002
#define IDE_DRIVEHEADREG_HS2                       0x00000004
#define IDE_DRIVEHEADREG_HS3                       0x00000008
#define IDE_DRIVEHEADREG_DRV                       0x00000010
#define IDE_DRIVEHEADREG_L                         0x00000040  // If set, operation = LBA. If cleared, operaton = CHS
#define IDE_DRIVEHEADREG_DEFAULTVALUE              0x000000A0
#define IDE_DRIVEHEADREG_PRIMARYDRIVE              0x00000000
#define IDE_DRIVEHEADREG_SECONDARYDRIVE            IDE_DRIVEHEADREG_DRV
#define IDE_DRIVEHEADREG_PRIMARYBITMASK            IDE_DRIVEHEADREG_DEFAULTVALUE | IDE_DRIVEHEADREG_PRIMARYDRIVE
#define IDE_DRIVEHEADREG_SECONDARYBITMASK          IDE_DRIVEHEADREG_DEFAULTVALUE | IDE_DRIVEHEADREG_SECONDARYDRIVE
 
// IDE, Status Register bitmask
#define IDE_STATUSREG_ERR                          0x00000001
#define IDE_STATUSREG_IDX                          0x00000002
#define IDE_STATUSREG_CORR                         0x00000004
#define IDE_STATUSREG_DRQ                          0x00000008
#define IDE_STATUSREG_DSC                          0x00000010
#define IDE_STATUSREG_DWF                          0x00000020
#define IDE_STATUSREG_DRDY                         0x00000040
#define IDE_STATUSREG_BSY                          0x00000080
//
#define IDE_FEATURESREG_ENABLE8BITTRANS            0x00000001
#define IDE_FEATURESREG_ENABLEWRITECACHE           0x00000002
#define IDE_FEATURESREG_SETTRANSFERMODE            0x00000003
#define IDE_FEATURESREG_DISABLERETRY               0x00000033
#define IDE_FEATURESREG_ECCLENGTH                  0x00000044
#define IDE_FEATURESREG_SETCACHESEGMENTS           0x00000054
#define IDE_FEATURESREG_DISABLELOOKAHEAD           0x00000055
#define IDE_FEATURESREG_DISABLERESET               0x00000066
#define IDE_FEATURESREG_DISABLEECC                 0x00000077
#define IDE_FEATURESREG_DISABLE8BITTRANS           0x00000081
#define IDE_FEATURESREG_ENABLEECC                  0x00000088
#define IDE_FEATURESREG_DISABLEWRITECHACHE         0x00000082
#define IDE_FEATURESREG_ENABLERETRIES              0x00000099
#define IDE_FEATURESREG_ENABLELOOKAHEAD            0x000000AA
#define IDE_FEATURESREG_SETMAXPREFETCH             0x000000AB
#define IDE_FEATURESREG_ENABLERESET                0x000000CC
//
// IDE, Error Register Bitmask
#define IDE_ERRORREG_AMNF                          0x00000001
#define IDE_ERRORREG_TK0NF                         0x00000002
#define IDE_ERRORREG_ABRT                          0x00000004
#define IDE_ERRORREG_MCR                           0x00000008
#define IDE_ERRORREG_IDNF                          0x00000010
#define IDE_ERRORREG_MC                            0x00000020
#define IDE_ERRORREG_UNC                           0x00000040
#define IDE_ERRORREG_BBK                           0x00000080
//
// IDE, Alternate Status Register Bitmask
#define IDE_ALTERNATESTATUSREG_ERR                 0x00000001
#define IDE_ALTERNATESTATUSREG_IDX                 0x00000002
#define IDE_ALTERNATESTATUSREG_CORR                0x00000004
#define IDE_ALTERNATESTATUSREG_DRQ                 0x00000008
#define IDE_ALTERNATESTATUSREG_DSC                 0x00000010
#define IDE_ALTERNATESTATUSREG_DWF                 0x00000020
#define IDE_ALTERNATESTATUSREG_DRDY                0x00000040
#define IDE_ALTERNATESTATUSREG_BSY                 0x00000080
 
// IDE, Device Control Register Bitmask
#define IDE_DEVICECONTROLREG_DEFAULTVALUE          0x00000008
#define IDE_DEVICECONTROLREG_nIEN                  0x00000002
#define IDE_DEVICECONTROLREG_SRST                  0x00000004
//
#define IDE_PRIMARY_CONTROLLER                     0x00000000
#define IDE_SECONDARY_CONTROLLER                   0x00000001
#define IDE_DRIVE0                                 0x00000000
#define IDE_DRIVE1                                 0x00000001

#endif

